/*
 * @Author: LC 1774939529@qq.com
 * @Date: 2023-11-05 17:49:02
 * @LastEditors: LC 1774939529@qq.com
 * @LastEditTime: 2023-11-12 13:28:59
 * @FilePath: \display_d_tube\RTL\IC_74HC595_2023_11.v
 * @Description: 这个是74HC595的驱动元件，8bit串并行转换，最高时钟：100Mhz/8
 * 
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved. 
 */

module IC_74HC595_2023_11 (
    input wire [7:0] data, 
	 input wire rst_n,
    input wire switch, //打开串并行转换
    input clk, //该时钟频率即串并转换时钟
    output reg OE_n, //不改变寄存器，控制输出为高阻
    output reg MR_n, //清除移位寄存器的数据
    output wire shift_clock_cp, //上升沿时提取ds的电平保存到移位寄存器最高位，其余位右移，
    output reg storage_clock_8div_cp, //上升沿时把移位寄存器的值保存到存储寄存器
    output reg data_s //串行数据线
);
    reg flag = 1'b1;
    reg [2:0] count = 3'b0;
    reg [7:0] data_t = 8'b0;

    assign shift_clock_cp = clk;

    /* 8计数器 */
    always @(posedge clk) begin
        if(rst_n == 1'b0) begin
            count <= 3'b0;
            flag <= 1'b1;
        end else begin
            if(count == 3'b111) begin
                flag <= 1'b1;
                count <= 3'b0;
            end else begin
                flag <= 1'b0;
                count <= count + 1'b1;
            end
        end
    end

    /* 控制串行数据转移到移位寄存器 */
    always @(posedge clk) begin
        if(rst_n == 1'b0) begin
            OE_n = 1'b1; //输出高阻
            MR_n = 1'b1; //清除移位寄存器
            data_t = 8'b0;
        end else begin
            OE_n = 1'b0;
            MR_n = 1'b0;
            if(flag == 1'b1) begin
                data_t = data;
                data_s = data_t[7];
            end else begin
				data_t = data_t << 1;
                data_s = data_t[7];
            end
        end
    end
	
	reg cp_flag = 1'b0;
    /* 当flag计数到达，并且允许转换，将触发把移位寄存器数据转移到存储寄存器的动作时钟 */
    always @(posedge clk) begin
        if(rst_n == 1'b0) begin
            cp_flag <= 1'b0;
        end else begin
            if(flag == 1'b1) begin
                if(switch == 1'b1) begin
                    cp_flag <= 1'b1;
                end else begin
                    cp_flag <= 1'b0;
                end
            end else begin
                cp_flag <= 1'b0;
            end
        end 
    end
    always @(posedge clk) begin
        if(rst_n == 1'b0) begin
            storage_clock_8div_cp <= 1'b0;
        end else begin
            if(cp_flag == 1'b1) begin
                storage_clock_8div_cp <= 1'b1;
            end else begin
                storage_clock_8div_cp <= 1'b0;
            end
        end 
    end
endmodule
